package cn.tedu.malldemo.controller;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.tedu.malldemo.entity.*;
import cn.tedu.malldemo.exception.ServiceException;
import cn.tedu.malldemo.mapper.ConfigMapper;
import cn.tedu.malldemo.mapper.RequestMapper;
import cn.tedu.malldemo.response.JsonResult;
import cn.tedu.malldemo.response.ResponseCode;
import cn.tedu.malldemo.service.IRequestService;
import cn.tedu.malldemo.service.IUrlService;
import cn.tedu.malldemo.service.IUserService;
import cn.tedu.malldemo.util.PasswordEncoder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author liuzhihao
 * @since 2022-07-22
 */
@Validated
@Transactional()
@Controller
@RequestMapping("/request")
@Slf4j
public class RequestController {

    private IUserService userService;
    private IUrlService urlService;
    private ConfigMapper configMapper;
    private IRequestService requestService;
    private RequestMapper requestMapper;

    @Autowired
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }
    @Autowired
    public void setUrlService(IUrlService urlService) {
        this.urlService = urlService;
    }
    @Autowired
    public void setConfigMapper(ConfigMapper configMapper) {
        this.configMapper = configMapper;
    }
    @Autowired
    public void setRequestService(IRequestService requestService) {
        this.requestService = requestService;
    }
    @Autowired
    public void setRequestMapper(RequestMapper requestMapper) {
        this.requestMapper = requestMapper;
    }

    @ResponseBody
    @GetMapping("/login")
    public ModelAndView login(){
        ModelAndView mav=new ModelAndView("login.html");
        return mav;
    }

    @ResponseBody
    @PostMapping("/dl")
    public JsonResult dl(@RequestBody @Valid User user){
        if("".equals(user.getUsername())||"".equals(user.getPassword())){
            throw new ServiceException(ResponseCode.NOT_ACCEPTABLE,"用户名或密码不能为空!");
        }
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("username",user.getUsername());
        User requestUser = userService.getOne(queryWrapper);
        if(requestUser==null){
            throw new ServiceException(ResponseCode.NOT_FOUND,"用户名不存在!");
        }
        PasswordEncoder encoder=new PasswordEncoder();
        if(!encoder.matches(user.getPassword(),requestUser.getPassword())){
            throw new ServiceException(ResponseCode.CONFLICT,"密码错误!");
        }
        StpUtil.login(requestUser.getId());
        log.debug("token:{}",StpUtil.getTokenInfo());
        return JsonResult.ok("登录成功!",requestUser);
    }

    @ResponseBody
    @GetMapping("/logout")
    public int  logout(){
        StpUtil.logout();
        return 0;
    }

    @SaCheckLogin
    @ResponseBody
    @GetMapping("/fsqq")
    public ModelAndView fsqq(Long id, String username){
        ModelAndView mav=new ModelAndView("fsqq.html");
        mav.addObject("id",id);
        mav.addObject("username",username);
        log.info("execute fsqq()");
        return mav;
    }

    @SaCheckLogin
    @SaCheckPermission("user-write")
    @ResponseBody
    @GetMapping("/cxqq")
    public JsonResult cxqq(Long id){
        return JsonResult.ok();
    }

    @SaCheckLogin
    @ResponseBody
    @GetMapping("/rzym")
    public ModelAndView rzym(){
        ModelAndView mav=new ModelAndView("cxqq.html");
        log.info("execute cxqq()");
        return mav;
    }

    @ResponseBody
    @GetMapping("/cxurl")
    public JsonResult cxurl(){
        List urlList=urlService.list();
        log.info("execute cxurl()");
        return JsonResult.ok("success",urlList);
    }

    @ResponseBody
    @GetMapping("/cxtype")
    public JsonResult cxtype(){
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("id","type");
        List type=configMapper.selectList(queryWrapper);
        System.out.println(type.toString());
        log.info("execute cxtype()");
        return JsonResult.ok("success",type);
    }

    @GetMapping("/cxrz")
    @ResponseBody
    public JsonResult cxrz(int pg){

        // 创建分页对象（1表示第一页；4表示每页大小为4）
        Page<Map<String,Object>> page = new Page<>(pg, 4);
        requestMapper.selectMapsPage(page, null);
        //System.out.println("size: " + page.getSize());
        //System.out.println("total: " + page.getTotal());
        //System.out.println("pages: " + page.getPages());
        /*ArrayList type=new ArrayList();
        for(Map<String, Object> map: page.getRecords()) {
            type.add(map);
        }*/
        PageResult pageResult = new PageResult();
        pageResult.setCurrentPage(page.getCurrent());
        pageResult.setPageSize(page.getPages());
        pageResult.setPageTotal(page.getTotal());
        pageResult.setData(page.getRecords());
        log.info("execute cxrz()");
        return JsonResult.ok("success",pageResult);
    }

    @GetMapping("/cxrzcount")
    @ResponseBody
    public long cxrzcount(){
        return requestService.count()/4+(requestService.count()%4!=0?1:0);
    }

    @GetMapping("/cxrznext")
    @ResponseBody
    public JsonResult cxrznext(int pg){
        int count=(int)requestService.count()/4+( (int)requestService.count() % 4 != 0 ? 1 : 0 );
        // 创建分页对象（1表示第一页；4表示每页大小为4）
        Page<Map<String,Object>> page = new Page<>(pg, 4);
        requestMapper.selectMapsPage(page, null);
        System.out.println("size: " + page.getSize());
        System.out.println("total: " + page.getTotal());
        System.out.println("pages: " + page.getPages());
        ArrayList type=new ArrayList();
        for(Map<String, Object> map: page.getRecords()) {
            type.add(map);
        }
        log.info("execute cxrz()");
        return JsonResult.ok("success",type);
    }

    @GetMapping("/cxrzlast")
    @ResponseBody
    public JsonResult cxrzlast(int pg){
        int count=(int)requestService.count()/4+( (int)requestService.count() % 4 != 0 ? 1 : 0 );
        // 创建分页对象（1表示第一页；4表示每页大小为4）
        Page<Map<String,Object>> page = new Page<>(pg, 4);
        requestMapper.selectMapsPage(page, null);
        System.out.println("size: " + page.getSize());
        System.out.println("total: " + page.getTotal());
        System.out.println("pages: " + page.getPages());
        ArrayList type=new ArrayList();
        for(Map<String, Object> map: page.getRecords()) {
            type.add(map);
        }
        log.info("execute cxrz()");
        return JsonResult.ok("success",type);
    }

    @SaCheckLogin
    @GetMapping("/tjget")
    @ResponseBody
    public JsonResult tjget(HttpServletRequest request,@Param("username")String username, @Param("password")String password){

        //程序执行前的时间戳
        long start = System.currentTimeMillis();

        if(username.length()==0&&password.length()==0){
            throw new ServiceException(ResponseCode.NOT_ACCEPTABLE,"用户名或密码为空!");
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("username",username);
        List count=userService.list(queryWrapper);
        if(count.size()>0){
            throw new ServiceException(ResponseCode.CONFLICT,"用户名重复!");
        }

        //添加请求参数到用户表
        User user=new User();
        user.setUsername(username);
        PasswordEncoder encoder=new PasswordEncoder();
        user.setPassword(encoder.encode(password));
        userService.save(user);

        //打印请求报文
        Enumeration<String> name = request.getHeaderNames();
        while(name.hasMoreElements()) {
            String headerName = name.nextElement();
            System.out.println("Header Name - " + headerName + ", Value - " + request.getHeader(headerName));
        }

        //添加请求信息到日志表
            //添加类型,请求报文到request数据库
        Request req=new Request();
        req.setType(request.getMethod());
        Enumeration<String> headerNames = request.getHeaderNames();
        req.setHost(request.getHeader(headerNames.nextElement()));
        req.setConnection(request.getHeader(headerNames.nextElement()));
        req.setSecChUa(request.getHeader(headerNames.nextElement()));
        req.setAccept(request.getHeader(headerNames.nextElement()));
        req.setSecChUaMobile(request.getHeader(headerNames.nextElement()));
        req.setUserAgent(request.getHeader(headerNames.nextElement()));
        req.setSecChUaPlatform(request.getHeader(headerNames.nextElement()));
        req.setSecFetchSite(request.getHeader(headerNames.nextElement()));
        req.setSecFetchMode(request.getHeader(headerNames.nextElement()));
        req.setSecFetchDest(request.getHeader(headerNames.nextElement()));
        req.setReferer(request.getHeader(headerNames.nextElement()));


            //添加请求参数到数据库
        StringBuilder param=new StringBuilder("{}");
        Enumeration<String> params = request.getParameterNames();
        while(params.hasMoreElements()){
            String paramName = params.nextElement();
            System.out.println("Parameter Name - "+paramName+", Value - "+
                    request.getParameter(paramName));
            param.insert(param.length()-1,"\""+paramName+"\":\""+
                    request.getParameter(paramName)+"\",");
        }
        param.deleteCharAt(param.length()-2);
        System.out.println(param);
        req.setParameter(param.toString());
        req.setState(200);

        //程序执行后的时间戳
        long end = System.currentTimeMillis();

        //将时间戳转换成我们想要的格式
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Date startDate = new Date(start);
        Date endDate = new Date(end);

        System.out.println("start time:" +formatter.format(startDate)+
                "; end time:" +formatter.format(endDate)+ "; Run Time:" + (end - start) + "(ms)");

        req.setStartTime(formatter.format(startDate));
        req.setEndTime(formatter.format(endDate));
        req.setRunTime((end-start)+"");
        requestService.save(req);

        log.info("execute tjget");
        return JsonResult.ok("添加成功!");

    }

    @SaCheckLogin
    @PostMapping("/tjpost")
    @ResponseBody
    public JsonResult tjpost(HttpServletRequest request,@RequestBody @Valid ReqObject reqObject){

        //程序执行前的时间戳
        long start = System.currentTimeMillis();
        //将字符串转换为Json对象
        JSONObject jsonObject=JSONUtil.parseObj(reqObject.getReq());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("username",jsonObject.getStr("username"));
        List count=userService.list(queryWrapper);
        if(count.size()>0){
            throw new ServiceException(ResponseCode.CONFLICT,"用户名重复!");
        }
        User user=new User();
        user.setUsername(jsonObject.getStr("username"));
        PasswordEncoder encoder=new PasswordEncoder();
        user.setPassword(encoder.encode(jsonObject.getStr("password")));
        userService.save(user);
        //打印请求报文
        Enumeration<String> name = request.getHeaderNames();
        while(name.hasMoreElements()) {
            String headerName = name.nextElement();
            System.out.println("Header Name - " + headerName + ", Value - " + request.getHeader(headerName));
        }
        //添加请求信息到日志表
        //添加类型,请求报文到request数据库
        Request req=new Request();
        req.setType(request.getMethod());
        Enumeration<String> headerNames = request.getHeaderNames();
        req.setHost(request.getHeader(headerNames.nextElement()));
        req.setConnection(request.getHeader(headerNames.nextElement()));
        request.getHeader(headerNames.nextElement());
        req.setSecChUa(request.getHeader(headerNames.nextElement()));
        req.setAccept(request.getHeader(headerNames.nextElement()));
        request.getHeader(headerNames.nextElement());
        req.setSecChUaMobile(request.getHeader(headerNames.nextElement()));
        req.setUserAgent(request.getHeader(headerNames.nextElement()));
        req.setSecChUaPlatform(request.getHeader(headerNames.nextElement()));
        request.getHeader(headerNames.nextElement());
        req.setSecFetchSite(request.getHeader(headerNames.nextElement()));
        req.setSecFetchMode(request.getHeader(headerNames.nextElement()));
        req.setSecFetchDest(request.getHeader(headerNames.nextElement()));
        req.setReferer(request.getHeader(headerNames.nextElement()));


        //添加请求参数到数据库
        req.setParameter(reqObject.getReq());
        req.setState(200);

        //程序执行后的时间戳
        long end = System.currentTimeMillis();

        //将时间戳转换成我们想要的格式
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Date startDate = new Date(start);
        Date endDate = new Date(end);

        System.out.println("start time:" +formatter.format(startDate)+
                "; end time:" +formatter.format(endDate)+ "; Run Time:" + (end - start) + "(ms)");
        req.setStartTime(formatter.format(startDate));
        req.setEndTime(formatter.format(endDate));
        req.setRunTime((end-start)+"");
        requestService.save(req);
        log.info("execute tjpost");
        return JsonResult.ok("添加成功!");
    }

}
